package edu.gatech.doi.spamframework.filters;

import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import weka.core.*;
import weka.core.stemmers.SnowballStemmer;
import weka.core.tokenizers.AlphabeticTokenizer;
import weka.core.tokenizers.Tokenizer;
import weka.core.tokenizers.WordTokenizer;
import weka.classifiers.*;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.evaluation.*;
import weka.classifiers.functions.SMO;
import weka.classifiers.trees.J48;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.NumericToNominal;
import weka.filters.unsupervised.attribute.Remove;
import weka.filters.unsupervised.attribute.Standardize;
import weka.filters.unsupervised.attribute.StringToWordVector;
import weka.gui.treevisualizer.PlaceNode1;
import weka.gui.treevisualizer.PlaceNode2;
import weka.gui.treevisualizer.TreeBuild;
import weka.gui.treevisualizer.TreeVisualizer;
import weka.gui.visualize.*;

/**
  * Generates and displays a ROC curve from a dataset. Uses a default 
  * NaiveBayes to generate the ROC data.
  *
  * @author FracPete
  */
public class GenerateROC {
	private String instancesdirectory=System.getProperties().getProperty("user.dir")+System.getProperties().getProperty("file.separator")+"instances"+System.getProperties().getProperty("file.separator");
	

	
	
	
  /**
   * takes one argument: dataset in ARFF format (expects class to 
   * be last attribute)
   */
  public static void main(String[] args) throws Exception {
    // load data
	  
 
    Instances data = new Instances(
                          new BufferedReader(
                            new FileReader(args[0])));
//    data.setClassIndex(data.numAttributes() - 1);

    String userdir=System.getProperties().getProperty("user.dir")+System.getProperties().getProperty("file.separator")+"properties"+System.getProperties().getProperty("file.separator");
    String stopwordsfile=userdir+"stopwords.txt";
    File stopwordfile=new File(stopwordsfile);
    /**
     * remove instanceid
     */
    Remove remove=new Remove();
    int [] attlist=new int[1];
    attlist[0]=data.numAttributes()-2;
    remove.setAttributeIndicesArray(attlist);
    
    remove.setInputFormat(data);
   Instances newdata= Filter.useFilter(data, remove);
    /**
     * string to word ,set stop words
     */
   StringToWordVector filter = new StringToWordVector();
   SnowballStemmer snowball=new SnowballStemmer();
   filter.setStemmer(snowball);
//   Tokenizer wt=new WordTokenizer();
   Tokenizer wt=new AlphabeticTokenizer();
	filter.setTokenizer(wt);
   filter.setInputFormat(newdata);
   filter.setStopwords(stopwordfile);
   Instances dataFiltered = Filter.useFilter(newdata, filter);
    
    
    NumericToNominal ntnfilter=new NumericToNominal();
    ntnfilter.setInputFormat(dataFiltered);
    Instances finaldata=Filter.useFilter(dataFiltered, ntnfilter);
    
    // train classifier
    //1: NaiveBayes; 2: Decision Trees j48; 3: Support Vector Machines: SMO;
//    Classifier cl = new NaiveBayes();
    Classifier cl=new weka.classifiers.bayes.NaiveBayesUpdateable();
    Evaluation eval=null;
    String classifiername="Classifier name: Naive Bayes ";
    int type=0;
    if(args.length>1)
    {
    	type = Integer.parseInt(args[1]);
    }

    switch(type)
    {
    	case 0:
    		
    		finaldata=Filter.useFilter(dataFiltered, ntnfilter);
    		break;
    	case 1:
    		cl = new NaiveBayes();
    		finaldata=Filter.useFilter(dataFiltered, ntnfilter);
    		classifiername="Classifier name: Naive Bayes ";
    		finaldata.setClassIndex(0);
    		eval = new Evaluation(finaldata);
    		eval.crossValidateModel(cl, finaldata, 10, new Random(1));
    		System.out.println(eval.toSummaryString("\nResults\n======\n", false));
    			    
    		break;
    	case 2:
    		J48 cls=new J48();
    		finaldata=Filter.useFilter(dataFiltered, ntnfilter);
    		classifiername="Classifier name: J48 ";
    		finaldata.setClassIndex(0);
    		
    		cls.buildClassifier(finaldata);
    		
    		 // display classifier
            final javax.swing.JFrame jf = 
              new javax.swing.JFrame("Weka Classifier Tree Visualizer: J48");
            jf.setSize(500,400);
            jf.getContentPane().setLayout(new BorderLayout());
            TreeVisualizer tv = new TreeVisualizer(null,
                cls.graph(),
                new PlaceNode2());
            jf.getContentPane().add(tv, BorderLayout.CENTER);
            jf.addWindowListener(new java.awt.event.WindowAdapter() {
              public void windowClosing(java.awt.event.WindowEvent e) {
                jf.dispose();
              }
            });
        
            jf.setVisible(true);
            tv.fitToScreen();
    		
    		
    		
    		eval = new Evaluation(finaldata);
    		eval.crossValidateModel(cls, finaldata, 10, new Random(1));
//    		System.out.println(eval.toString());
//    		
    		
    	System.out.println(cls.toSummaryString());
    	System.out.println(cls.graph());
    	
//    	 String[] options = new String[2];
//    	 options[0] = "-t";
//    	 options[1] = userdir+"j48results.arff";
//    	 System.out.println(Evaluation.evaluateModel(cls, options));
    		System.out.println(eval.toSummaryString("\nResults\n======\n", true));
    	    
    		
    		
    	
    			 
//    		System.out.println(j.globalInfo());
    		break;
    	case 3:
    		cl=new SMO();
    		finaldata=Filter.useFilter(dataFiltered, ntnfilter);
    		classifiername="Classifier name: SMO";
    		finaldata.setClassIndex(0);
    		eval = new Evaluation(finaldata);
    		eval.crossValidateModel(cl, finaldata, 10, new Random(1));
    		System.out.println(eval.toSummaryString("\nResults\n======\n", false));
    			
    		break;
    			
    }
    
   
	    double[][] tempdou=eval.confusionMatrix();
		 for(int i=0;i<tempdou.length;i++)
		 {
			 System.out.println(tempdou[i][0]+" "+tempdou[i][1]);
			 
		 }
    double TP,FP,FN,TN;
    TP=tempdou[0][0];
    FP=tempdou[0][1];
    FN=tempdou[1][0];
    TN=tempdou[1][1];
    double FPR=FP/(FP+TN);
    double FNR=FN/(TP+FN);
    System.out.println("FPR:"+FPR+" FNR:"+FNR);

    
    // generate curve
    ThresholdCurve tc = new ThresholdCurve();
    int classIndex = 0;
    Instances result = tc.getCurve(eval.predictions(), classIndex);

    // plot curve
    ThresholdVisualizePanel vmc = new ThresholdVisualizePanel();
    vmc.setROCString("(Area under ROC = " + 
        Utils.doubleToString(tc.getROCArea(result), 4) + ")");
    vmc.setName(result.relationName());
    PlotData2D tempd = new PlotData2D(result);
    tempd.setPlotName(result.relationName());
    tempd.addInstanceNumberAttribute();
    // specify which points are connected
    boolean[] cp = new boolean[result.numInstances()];
    for (int n = 1; n < cp.length; n++)
      cp[n] = true;
    tempd.setConnectPoints(cp);
    // add plot
    vmc.addPlot(tempd);

    // display curve
    String plotName = vmc.getName()+"  "+classifiername; 
    final javax.swing.JFrame jf = 
      new javax.swing.JFrame("Weka Classifier Visualize: "+plotName);
    jf.setSize(500,400);
    jf.getContentPane().setLayout(new BorderLayout());
    jf.getContentPane().add(vmc, BorderLayout.CENTER);
    jf.addWindowListener(new java.awt.event.WindowAdapter() {
      public void windowClosing(java.awt.event.WindowEvent e) {
      jf.dispose();
      }
    });
    jf.setVisible(true);
  }

}

